package com.xunwulian.web.util;

import com.xunwulian.base.exception.PayException;
import com.xunwulian.base.param.WeixinParam;
import com.xunwulian.base.util.BeanUtil;
import com.xunwulian.base.util.MD5Util;
import com.xunwulian.web.bean.WeixinCallback;
import com.xunwulian.web.bean.WeixinEntity;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2016/12/20.
 */
public class WeiXinUtil {

    private QRUtil qrUtil = new QRUtil();

    private BeanUtil beanUtil = new BeanUtil();

    /**
     * 生成本地二维码文件
     *
     * @param pay
     * @param path
     * @return
     */
    public String payForFile(WeixinEntity pay, String path) {
        String file_path = null;
        String code_url = payForCodeUrl(pay);
        try {
            file_path = qrUtil.generateQR(code_url, path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file_path;
    }


    /**
     * 返回二维码字节数组
     *
     * @param pay
     * @return
     */
    public byte[] payForByteArray(WeixinEntity pay) {
        String code_url = payForCodeUrl(pay);
        return qrUtil.generateQR(code_url);
    }

    /**
     * 返回二维码字串
     *
     * @param pay
     * @return
     */
    public String payForCodeUrl(WeixinEntity pay) {
        String code_url = null;
        try {
            code_url = qrUtil.requestCodeUrl(pay.generateParamMap());
        } catch (PayException e) {
            e.printStackTrace();
        }
        return code_url;
    }

    /**
     * 将回调的xml数据封装成对象
     *
     * @param req
     * @return
     * @throws IOException
     */
    public WeixinCallback parseCallback(HttpServletRequest req) throws IOException {
        InputStream inStream = req.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();

        byte[] buffer = new byte[1024];
        int len;

        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }

        outSteam.close();
        inStream.close();

        // 获取微信调用我们notify_url的返回信息
        String xml = new String(outSteam.toByteArray(), WeixinParam.CHAR_SET);

        return new WeixinCallback(parseCallback(xml));
    }


    /**
     * 将回调的xml数据封装到map里
     *
     * @param xml
     * @return
     */
    public Map<String, String> parseCallback(String xml) {
        Document document = null;
        try {
            document = DocumentHelper.parseText(xml);
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        if (document == null) {
            return null;
        }

        // 回调结果打印
        beanUtil.log(xml);

        Element root = document.getRootElement();
        List<Element> elements = root.elements();

        Map<String, String> paramMap = new HashMap();

        for (Element element : elements) {
            String name = element.getName();
            String value = element.getText();
            paramMap.put(name, value);
        }

        return paramMap;
    }

    /**
     * MD5签名,专门用于微信
     *
     * @param params     参数
     * @param keys       排序的参数key
     * @param privateKey 私钥
     * @return 签名
     */
    public static String signByMD5(Map<String, String> params, Collection<String> keys, String privateKey) {
        StringBuilder signTemp = new StringBuilder();
        for (String key : keys) {
            String value = params.get(key);
            signTemp.append("&" + key + "=" + value);
        }
        signTemp.append("&key" + "=" + privateKey);

        // 将签名全部转换为大写
        return MD5Util.MD5Encode(signTemp.substring(1, signTemp.length()), WeixinParam.CHAR_SET).toUpperCase();
    }
}
